/**
 *  Copyright 2010 Kyle O'Connor, Justin Arling, Mike Mercieca
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  any later version.
 *  
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */
package edu.drexel.sd0910.ece01.aqmon.manager;

import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import edu.drexel.sd0910.ece01.aqmon.gui.MainModel;
import edu.drexel.sd0910.ece01.aqmon.util.run.ExecutorServiceProvider;

/**
 * Abstract class representing an object to manage something. This manager also
 * implements the <code>{@link ExecutorServiceProvider}</code> to provide a way
 * for the manager to run tasks and the
 * <code>{@link ManagerTaskController}</code> interface for controlling these
 * tasks.
 * 
 * @author Kyle O'Connor
 * 
 */
public abstract class Manager implements ExecutorServiceProvider, ManagerTaskController {

	protected MainModel model;
	protected Properties props;

	private ExecutorService executor = null;
	private String executorServiceImplemenation;

	/**
	 * Constructor for the abstract <code>Manager</code>. Must be called using
	 * <code>super</code>. You must set the <code>ExecutorService</code>
	 * implementation using the {@link #setExecutorType(String)} method.
	 * 
	 * @param model
	 *            the data model for the <code>Manager</code>
	 * @param props
	 *            properties object from the model
	 */
	public Manager(MainModel model, Properties props) {
		super();
		this.model = model;
		this.props = props;
	}

	/**
	 * Constructor for the abstract <code>Manager</code>. Must be called using
	 * <code>super</code>.
	 * 
	 * @param model
	 *            the data model for the <code>Manager</code>
	 * @param props
	 *            properties object from the model
	 * @param executorType
	 *            <code>ExecutorService</code> implementation type to use
	 */
	public Manager(MainModel model, Properties props, String executorType) {
		super();
		this.model = model;
		this.props = props;
		setExecutorType(executorType);
	}

	public MainModel getModel() {
		return model;
	}

	public void setModel(MainModel model) {
		this.model = model;
	}

	public Properties getProps() {
		return props;
	}

	public void setProps(Properties props) {
		this.props = props;
	}

	/**
	 * Abstract method to specify the shutdown procedure for a
	 * <code>Manager</code>.
	 * 
	 * @throws Exception
	 *             if any error occurs during shutdown
	 */
	public abstract void shutdown() throws Exception;

	public ExecutorService getExecutorService() {
		if (executor == null) {
			if (executorServiceImplemenation.equals(NEW_SCHEDULED_THREAD_POOL)) {
				// create a new scheduled thread pool executor with 2 threads
				executor = Executors.newScheduledThreadPool(2);
			} else if (executorServiceImplemenation.equals(NEW_SINGLE_THREAD_EXECUTOR)) {
				// create a single thread executor
				executor = Executors.newSingleThreadExecutor();
			} else if (executorServiceImplemenation.equals(NEW_SINGLE_THREAD_SCHEDULED_EXECUTOR)) {
				// create a single thread scheduled executor
				executor = Executors.newSingleThreadScheduledExecutor();
			} else {
				executor = Executors.newCachedThreadPool();
			}
		}
		return executor;
	}

	public void stopExecutorService() {
		if (executor != null) {
			executor.shutdownNow();
			// must null it so we can restart
			executor = null;
		}
	}

	public void setExecutorType(String methodString) {
		this.executorServiceImplemenation = methodString;
	}

	/**
	 * This method is purposely left empty to allow <code>Manager</code>
	 * subclasses to choose whether or not to implement it.
	 * 
	 * @see edu.drexel.sd0910.ece01.aqmon.manager.ManagerTaskController#startAllTasks()
	 */
	public void startAllTasks() { }

	/**
	 * This method is purposely left empty to allow <code>Manager</code>
	 * subclasses to choose whether or not to implement it.
	 * 
	 * @see edu.drexel.sd0910.ece01.aqmon.manager.ManagerTaskController#stopAllTasks()
	 */
	public void stopAllTasks() { }

}
